package com.bleeth.flow.core.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.CalendarUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.lang.id.NanoId;
import cn.hutool.core.math.Calculator;
import cn.hutool.core.math.MathUtil;
import cn.hutool.core.net.Ipv4Util;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.text.TextSimilarity;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.AviatorEvaluatorInstance;
import com.googlecode.aviator.Feature;
import com.googlecode.aviator.Options;

import java.util.List;
import java.util.Map;

/**
 * @author BleethNie
 * @version 1.0
 * @date 2021/7/28 16:27
 **/
public class AviatorUtil {


    private static AviatorEvaluatorInstance instance = AviatorEvaluator.newInstance();

    private static boolean first = true;

    private static List<String> funcNameList = CollUtil.newArrayList();

    private static void importFunction() {
        try {
            List<String> funcs = instance.addStaticFunctions("StrUtil", StrUtil.class);
            funcNameList.addAll(funcs);
            //日期处理类工具
            funcs = instance.addInstanceFunctions("DateTime", DateTime.class);
            funcNameList.addAll(funcs);

            funcs = instance.addStaticFunctions("DateUtil", DateUtil.class);
            funcNameList.addAll(funcs);

            funcs = instance.addStaticFunctions("CalendarUtil", CalendarUtil.class);
            funcNameList.addAll(funcs);

            //字符串处理工具，文本相似度
            funcs = instance.addStaticFunctions("TextSimilarity", TextSimilarity.class);
            funcNameList.addAll(funcs);

            //正则表达式处理工具
            funcs = instance.addStaticFunctions("ReUtil", ReUtil.class);
            funcNameList.addAll(funcs);

            //随机数工具
            funcs = instance.addStaticFunctions("RandomUtil", RandomUtil.class);
            funcNameList.addAll(funcs);

            //唯一URL字符串生成工具
            funcs = instance.addStaticFunctions("NanoId", NanoId.class);
            funcNameList.addAll(funcs);

            //UUID生成工具
            funcs = instance.addStaticFunctions("UUID", UUID.class);
            funcNameList.addAll(funcs);

            funcs = instance.addStaticFunctions("IdUtil", IdUtil.class);
            funcNameList.addAll(funcs);

            //校验工具
            funcs = instance.addStaticFunctions("Validator", Validator.class);
            funcNameList.addAll(funcs);

            //IPV4工具类
            funcs = instance.addStaticFunctions("Ipv4Util", Ipv4Util.class);
            funcNameList.addAll(funcs);

            funcs = instance.addStaticFunctions("NetUtil", NetUtil.class);
            funcNameList.addAll(funcs);

            //计算器
            funcs = instance.addStaticFunctions("Calculator", Calculator.class);
            funcNameList.addAll(funcs);

            funcs = instance.addStaticFunctions("MathUtil", MathUtil.class);
            funcNameList.addAll(funcs);

            //数学计算
            funcs = instance.addStaticFunctions("NumberUtil", NumberUtil.class);
            funcNameList.addAll(funcs);

            //身份证工具类
            funcs = instance.addStaticFunctions("IdcardUtil", IdcardUtil.class);
            funcNameList.addAll(funcs);

            funcs = instance.addStaticFunctions("PhoneUtil", PhoneUtil.class);
            funcNameList.addAll(funcs);
            //URL工具类

        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

    }

    public static void setInstance() {
        instance.setOption(Options.USE_USER_ENV_AS_TOP_ENV_DIRECTLY, false);
        instance.setOption(Options.FEATURE_SET,
                Feature.asSet(Feature.Assignment,
                        Feature.ForLoop,
                        Feature.WhileLoop,
                        Feature.Lambda,
                        Feature.Use,
                        Feature.Return,
                        Feature.NewInstance,
                        Feature.Let));
    }


    /**
     * 执行通用表达式
     *
     * @param expresion
     * @param paramMap
     * @return
     */
    public static Object exec(String expresion, Map<String, Object> paramMap) {
        if (first) {
            first = false;
            setInstance();
            importFunction();
        }

        Object obj = instance.execute(expresion, paramMap, true);
        return obj;
    }

    public static boolean execBoolean(String expresion, Map<String, Object> paramMap) {
        Object obj = exec(expresion, paramMap);
        return Convert.toBool(obj);
    }

    public static Long execLong(String expresion, Map<String, Object> paramMap) {
        Object obj = exec(expresion, paramMap);
        return Convert.toLong(obj);
    }

    public static String execStr(String expresion, Map<String, Object> paramMap) {
        Object obj = exec(expresion, paramMap);
        return Convert.toStr(obj);
    }

    public static Integer execInt(String expresion, Map<String, Object> paramMap) {
        Object obj = exec(expresion, paramMap);
        return Convert.toInt(obj);
    }
}
